
package helpers;
import java.awt.image.BufferedImage;
/**
 * 2D grey scale image filter with nxm tap support 
 * @author benjamin
 	This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
public class Filter {
	static final int MAX_INTENSITY = 255;
	
	float[][] filter;
	int w,h,cX,cY;
	/**
	 * Default constructor for filter
	 * @param data 2D matrix containing filter taps
	 * @param w width
	 * @param h height
	 * @param cX center tap (X) of the filter
	 * @param cY center tap (Y) of the filter
	 */
	public Filter(float[][] data, int w, int h, int cX, int cY) {
		filter = new float[h][w];
		//deep copy:
		for (int i = 0; i < h; ++i)
			for (int j = 0; j < w; ++j)
				filter[i][j] = data[i][j];
		this.w = w;
		this.h = h;
		this.cX = cX;
		this.cY = cY;
	}
	/**
	 * Applies the filter to the specified image. Returns new image (arguement img is not modified).
	 * @param img
	 * @return new filtered image
	 */
	public BufferedImage apply(BufferedImage img){
		BufferedImage result = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_BYTE_GRAY);
		for (int iY = 0; iY < img.getHeight(); ++iY)
			for (int iX = 0; iX < img.getWidth(); ++iX){ //loop through every pixel in the image
				float sum = 0;
				for (int y = 0; y < h; ++y)
					for (int x = 0; x < w; ++x){ //and sum up the tap-contributions of the filter
						int addrX = Math.abs(iX+(x-cX));
						addrX -= (addrX >= img.getWidth()) ? x : 0;
						int addrY = Math.abs(iY+(y-cY));
						addrY -= (addrY >= img.getHeight()) ? y : 0;
						sum += filter[y][x]*img.getRaster().getPixel(addrX, addrY, new int[1])[0];
					}
				int arg[] = {(int)Math.max(Math.min(sum,MAX_INTENSITY),0)};
				result.getRaster().setPixel(iX, iY, arg); //set the current pixel
			}	
		return result;
	}
}
